﻿using System.Collections.Generic;
using System.Linq;

namespace Tuxedo.Compile
{
	internal class TryBlock : CodeLine
	{
		private CodeLine[] tryCode;
		private CodeLine[][] catchCode;
		private UnverifiedType[] catchExceptionTypes;
		private string[] exceptionVariableNames;
		private CodeLine[] finallyCode;

		public TryBlock(IList<CodeLine> tryCode, IList<CodeLine[]> catchCodes, IList<UnverifiedType> exceptionTypes, IList<string> exceptionVarNames, IList<CodeLine> finallyCode)
		{
			this.tryCode = tryCode.ToArray();
			this.catchCode = catchCodes.ToArray();
			this.catchExceptionTypes = exceptionTypes.ToArray();
			this.exceptionVariableNames = exceptionVarNames.ToArray();
			this.finallyCode = finallyCode.ToArray();
		}

		public static CodeLine Parse(TokenStream tokens)
		{
			tokens.PopExpected("try");
			IList<CodeLine> tryCode = CodeLine.ParseBlock(tokens, false);
			List<CodeLine[]> catchCodes = new List<CodeLine[]>();
			List<UnverifiedType> catchTypes = new List<UnverifiedType>();
			List<string> catchNames = new List<string>();
			while (tokens.PopIfPresent("catch"))
			{
				tokens.PopExpected("(");
				UnverifiedType type = UnverifiedType.Parse(tokens, false);
				string name = null;
				if (!tokens.IsNext(")"))
				{
					name = tokens.PopIdentifier();
				}
				tokens.PopExpected(")");
				CodeLine[] catchCode = CodeLine.ParseBlock(tokens, false).ToArray();

				catchCodes.Add(catchCode);
				catchTypes.Add(type);
				catchNames.Add(name);
			}

			IList<CodeLine> finallyCode = CodeLine.NO_LINES;
			if (tokens.PopIfPresent("finally"))
			{
				finallyCode = CodeLine.ParseBlock(tokens, false);
			}

			return new TryBlock(tryCode, catchCodes, catchTypes, catchNames, finallyCode);
		}
	}
}
